#include "../liolib/lioflat.h"

#include <Vfw.h>
#pragma comment( lib, "Vfw32.lib" )					// Search For Vfw32.lib While Linking

#define INIT_FILE _T("VideoCapture.ini")
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
#define DEFAULT_COMPS 1
#define DEFAULT_FPS 10
#define DEFAULT_QUAD 4
#define DEFAULT_THRES 0.25
#define DEFAULT_JPEG 75
#define DEFAULT_DEVICE 0
#define DEFAULT_HISTORY 100

#define DIFF_TO_MOTION 0.00390625

typedef Vector<BYTE> Array;
typedef Rect<WORD> Zone;

struct DEVICE
{
	char name[80], version[100];
};
struct OUTPUT
{
	_TCHAR name[MAX_PATH];
	Image image;
};
LRESULT PASCAL StatusProc(HWND hWnd, int nID, LPSTR lpStatusText);
LRESULT PASCAL ErrorProc(HWND hWnd, int nID, LPSTR lpText);
LRESULT PASCAL FrameProc(HWND hWnd, LPVIDEOHDR lpVHdr);

class VideoCapture:public FlatApplication
{
protected:
	ThreadInfo
		frame_thread,
		grab_thread,
		save_thread,
		connect_thread,
		play_thread;

	HWND hWndC;
	DEVICE devices[10];
	int device_count,device_connected,device_to_connect,
		status_id,error_id,frame_count,fps,sleep_time,history,
		jpg_quality,img_left,img_bot,grab_time,op_time,frame_time;
	DWORD image_size,quad_size,levels_size,frame_size;
	BYTE frame_comps,diff_max,diff_mid,lev_max,lev_min;
	WORD quad_dx,quad_dy,quad_dim,frame_width,frame_height,levels_width,levels_height;
	float motion_thres,inflate;
	BOOL observe_only;
	double motion, motion_time;
	
	CAPDRIVERCAPS caps;
	CAPSTATUS status;
	CAPTUREPARMS params;
	WAVEFORMATEX audio_format;
	BITMAPINFO *video_format;
	BITMAPINFOHEADER *header;
	RGBQUAD *palette;
	VIDEOHDR *frame;
	_TCHAR output_dir[MAX_PATH],path[MAX_PATH];
	String error_str,status_str;
	BOOL frame_done,frame_prepared,frame_key;
	List<Array> frames;
	List<OUTPUT> outputs;
	List<Zone> zones;
	Zone *new_zone;
	Array buffer;
	Vector<DWORD> levels;
	Vector<BYTE> mask;
	Image image,read_image,diff;
	PrecisionTimer frame_timer;
	CriticalSection cs, cs_capture, cs_frame;
	Event eventFrame,eventOutput;
	SYSTEMTIME date;
	Point2d<WORD> mouse_start,mouse_end;
	Directory folder;
	Channel *chFrame,*chMotion;

	FlatButton bCapture,bPlay,bStop,bLoop;
	FlatChoice chDevice;
	FlatImage iFrame,iDiff;
	FlatPlotter graph;
	
	BOOL Connect(int device_index);
	void updateMask();
	void Disconnect();
	void stop(){folder.set();Disconnect();}
	BOOL create();
	BOOL glCreate();
	void glDestroy();
	void destroy();
	void reshape ();
	BOOL listen(WORD id, WORD code, const void *info);
	void update();
	void draw2Dpost();
	BOOL initFrame();
	void resetGraph();
	//BOOL input(BYTE type);
	DWORD run(const ThreadInfo *info);
public:
	BOOL OnStatus(int id, LPSTR text);
	BOOL OnError(int id, LPSTR text);
	BOOL OnFrame(LPVIDEOHDR frame);
};